Add a new filter `to_uri`.

Akinori MUSHA 10 years ago
parent
commit
ca6de90fc5

+ 16 - 0
app/concerns/liquid_droppable.rb

@@ -27,4 +27,20 @@ module LiquidDroppable
27 27
   def to_liquid
28 28
     self.class::Drop.new(self)
29 29
   end
30
+
31
+  require 'uri'
32
+
33
+  class URIDrop < Drop
34
+    URI::Generic::COMPONENT.each { |attr|
35
+      define_method(attr) {
36
+        @object.__send__(attr)
37
+      }
38
+    }
39
+  end
40
+
41
+  class ::URI::Generic
42
+    def to_liquid
43
+      URIDrop.new(self)
44
+    end
45
+  end
30 46
 end

+ 16 - 0
app/concerns/liquid_interpolatable.rb

@@ -116,6 +116,22 @@ module LiquidInterpolatable
116 116
       CGI.escape(string) rescue string
117 117
     end
118 118
 
119
+    # Parse an input into a URI object, optionally resolving it
120
+    # against a base URI if given.
121
+    #
122
+    # A URI object will have the following properties: scheme,
123
+    # userinfo, host, port, registry, path, opaque, query, and
124
+    # fragment.
125
+    def to_uri(uri, base_uri = nil)
126
+      if base_uri
127
+        URI(base_uri) + uri.to_s
128
+      else
129
+        URI(uri.to_s)
130
+      end
131
+    rescue URI::Error
132
+      nil
133
+    end
134
+
119 135
     # Escape a string for use in XPath expression
120 136
     def to_xpath(string)
121 137
       subs = string.to_s.scan(/\G(?:\A\z|[^"]+|[^']+)/).map { |x|

+ 37 - 0
spec/concerns/liquid_interpolatable_spec.rb

@@ -59,4 +59,41 @@ describe LiquidInterpolatable::Filters do
59 59
       @filter.to_xpath_roundtrip(1).should == '1'
60 60
     end
61 61
   end
62
+
63
+  describe 'to_uri' do
64
+    before do
65
+      @agent = Agents::InterpolatableAgent.new(name: "test", options: { 'foo' => '{% assign u = s | to_uri %}{{ u.path }}' })
66
+      @agent.interpolation_context['s'] = 'http://example.com/dir/1?q=test'
67
+    end
68
+
69
+    it 'should parse an abosule URI' do
70
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
71
+    end
72
+
73
+    it 'should parse an abosule URI with a base URI specified' do
74
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
75
+    end
76
+
77
+    it 'should parse a relative URI with a base URI specified' do
78
+      @filter.to_uri('foo/index.html', 'http://example.com/dir/1').should == URI('http://example.com/dir/foo/index.html')
79
+    end
80
+
81
+    it 'should parse an abosule URI with a base URI specified' do
82
+      @filter.to_uri('http://example.net/index.html', 'http://example.com/dir/1').should == URI('http://example.net/index.html')
83
+    end
84
+
85
+    it 'should stringify a non-string operand' do
86
+      @filter.to_uri(123, 'http://example.com/dir/1').should == URI('http://example.com/dir/123')
87
+    end
88
+
89
+    it 'should return a URI value in interpolation' do
90
+      @agent.interpolated['foo'].should == '/dir/1'
91
+    end
92
+
93
+    it 'should return a URI value resolved against a base URI in interpolation' do
94
+      @agent.options['foo'] = '{% assign u = s | to_uri:"http://example.com/dir/1" %}{{ u.path }}'
95
+      @agent.interpolation_context['s'] = 'foo/index.html'
96
+      @agent.interpolated['foo'].should == '/dir/foo/index.html'
97
+    end
98
+  end
62 99
 end